package com.yao2san.sim.storage.client.core.uploader;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.PutObjectRequest;
import com.yao2san.sim.storage.client.util.StorageUtil;
import com.yao2san.sim.storage.client.config.TencentCosProperties;
import com.yao2san.sim.storage.client.core.enums.StorageType;
import com.yao2san.sim.storage.client.core.event.UploadEvent;
import com.yao2san.sim.storage.client.core.event.UploadResult;
import com.yao2san.sim.storage.client.core.listener.TencentCosProgressListener;
import com.yao2san.sim.storage.client.core.policy.FolderPolicy;
import com.yao2san.sim.storage.client.exception.UploadErrorException;
import org.apache.commons.io.FilenameUtils;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author wxg
 **/
public class TencentCosUploader extends AbstractUploader {
    private final COSClient client;

    private final TencentCosProperties tencentCosProperties;

    private final ApplicationContext applicationContext;
    private final FolderPolicy folderPolicy;

    public TencentCosUploader(COSClient client, TencentCosProperties tencentCosProperties, ApplicationContext applicationContext, FolderPolicy folderPolicy) {
        this.client = client;
        this.tencentCosProperties = tencentCosProperties;
        this.applicationContext = applicationContext;
        this.folderPolicy = folderPolicy;
    }


    @Override
    public UploadResult upload(InputStream stream, String dest, UploadArgs args) throws IOException, UploadErrorException {
        String object = getObject(dest, args);
        int size = stream.available();


        String endpoint = tencentCosProperties.getEndpoint();
        String bucket = tencentCosProperties.getBucket();
        PutObjectRequest request = new PutObjectRequest(bucket, object, stream, null)
                .withGeneralProgressListener(new TencentCosProgressListener());
        com.qcloud.cos.model.PutObjectResult putObjectResult = client.putObject(request);
        //publish event
        UploadResult result = UploadResult.builder()
                .object(object)
                .size((long) size)
                .url(getUrl(endpoint, bucket, object))
                .uploadArgs(args)
                .success(true)
                .build();
        applicationContext.publishEvent(new UploadEvent(result));

        if (args != null && args.getCallback() != null) {
            args.getCallback().callback(result);
        }
        return result;
    }

    private String getObject(String dest, UploadArgs args) {
        String dir = this.folderPolicy.create();
        String name = FilenameUtils.getName(dest);
        String path = FilenameUtils.getPath(dest);
        if (args != null) {
            FolderPolicy fp = args.getFolderPolicy();
            if (fp != null) {
                dir = fp.create();
            }
        }
        String object = getBasePath() + "/" + dir + "/" + path + "/" + name;
        object = StorageUtil.formatPath(object);
        //COS的object不能以/开头
        if (object.startsWith("/")) {
            object = object.substring(1);
        }
        return object;
    }

    private String getUrl(String endpoint, String bucket, String object) {
        return bucket + "." + endpoint + "/" + object;
    }

    @Override
    public String getBasePath() {
        return tencentCosProperties.getPath();
    }

    @Override
    public String getName() {
        return StorageType.TENCENT_COS.name();
    }
}
